package com.cah.project.util;

import cn.hutool.core.util.NumberUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 功能描述: BigDecimal的链式计算 <br/>
 * 依赖hutool 的 NumberUtil
 */
public class BigDecimalChain {

    /** 返回结果*/
    private BigDecimal result;

    private BigDecimalChain(BigDecimal result) {
        this.result = result;
    }

    /**
     * 功能描述: 构造链 <br/>
     */
    public static BigDecimalChain chain(BigDecimal bd) {
        return new BigDecimalChain(bd);
    }

    /**
     * 功能描述: 构造链 <br/>
     */
    public static BigDecimalChain chain(String bd) {
        isNumber(bd);
        return new BigDecimalChain(new BigDecimal(bd));
    }

    /**
     * 功能描述: 构造链 <br/>
     */
    public static BigDecimalChain chain(long bd) {
        return new BigDecimalChain(BigDecimal.valueOf(bd));
    }

    /**
     * 功能描述: 构造链 <br/>
     */
    public static BigDecimalChain chain(double bd) {
        return new BigDecimalChain(BigDecimal.valueOf(bd));
    }

    /** 加 */
    public BigDecimalChain add(BigDecimal v) {
        this.result = result.add(v);
        return this;
    }

    /** 加 */
    public BigDecimalChain add(String v) {
        isNumber(v);
        this.result = result.add(new BigDecimal(v));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(String... vs) {
        this.result = result.add(NumberUtil.add(vs));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(int v1) {
        this.result = result.add(new BigDecimal(Integer.toString(v1)));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(float v1) {
        this.result = result.add(new BigDecimal(Float.toString(v1)));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(double v1) {
        this.result = result.add(new BigDecimal(Double.toString(v1)));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(int v1, int v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(float v1, float v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(float v1, double v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(double v1, float v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(double v1, double v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Integer v1) {
        this.result = result.add(new BigDecimal(v1));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Float v1) {
        this.result = result.add(new BigDecimal(v1));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Double v1) {
        this.result = result.add(new BigDecimal(v1));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Float v1, Float v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Double v1, Double v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Integer... vs) {
        this.result = result.add(NumberUtil.add(vs));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Float... vs) {
        this.result = result.add(NumberUtil.add(vs));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Double... vs) {
        this.result = result.add(NumberUtil.add(vs));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Number... vs) {
        this.result = result.add(NumberUtil.add(vs));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(BigDecimal v) {
        this.result = result.subtract(v);
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(String v) {
        isNumber(v);
        this.result = result.subtract(new BigDecimal(v));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(int v) {
        this.result = result.subtract(new BigDecimal(Integer.toString(v)));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(float v) {
        this.result = result.subtract(new BigDecimal(Float.toString(v)));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(double v) {
        this.result = result.subtract(new BigDecimal(Double.toString(v)));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(Integer v) {
        this.result = result.subtract(new BigDecimal(v));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(Float v) {
        this.result = result.subtract(new BigDecimal(v));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(Double v) {
        this.result = result.subtract(new BigDecimal(v));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(BigDecimal v) {
        this.result = result.multiply(v);
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(String v) {
        isNumber(v);
        this.result = result.multiply(new BigDecimal(v));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(int v) {
        this.result = result.multiply(new BigDecimal(Integer.toString(v)));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(float v) {
        this.result = result.multiply(new BigDecimal(Float.toString(v)));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(double v) {
        this.result = result.multiply(new BigDecimal(Double.toString(v)));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(Integer v) {
        this.result = result.multiply(new BigDecimal(v));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(Float v) {
        this.result = result.multiply(new BigDecimal(v));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(Double v) {
        this.result = result.multiply(new BigDecimal(v));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(BigDecimal v) {
        this.result = result.divide(v);
        return this;
    }

    /** 除 */
    public BigDecimalChain div(String v) {
        isNumber(v);
        this.result = result.divide(new BigDecimal(v));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(int v) {
        this.result = result.divide(new BigDecimal(Integer.toString(v)));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(float v) {
        this.result = result.divide(new BigDecimal(Float.toString(v)));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(double v) {
        this.result = result.divide(new BigDecimal(Double.toString(v)));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(Integer v) {
        this.result = result.divide(new BigDecimal(v));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(Float v) {
        this.result = result.divide(new BigDecimal(v));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(Double v) {
        this.result = result.divide(new BigDecimal(v));
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(BigDecimal v, int scale) {
        this.result = result.divide(v, scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(String v, int scale) {
        isNumber(v);
        this.result = result.divide(new BigDecimal(v), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(int v, int scale) {
        this.result = result.divide(new BigDecimal(Integer.toString(v)), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(float v, int scale) {
        this.result = result.divide(new BigDecimal(Float.toString(v)), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(double v, int scale) {
        this.result = result.divide(new BigDecimal(Double.toString(v)), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(Integer v, int scale) {
        this.result = result.divide(new BigDecimal(v), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(Float v, int scale) {
        this.result = result.divide(new BigDecimal(v), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(Double v, int scale) {
        this.result = result.divide(new BigDecimal(v), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 保留小数模式 */
    public BigDecimalChain div(BigDecimal div, int scale, RoundingMode roundingMode) {
        this.result = result.divide(div, scale, roundingMode);
        return this;
    }

    /** 精度 */
    public BigDecimalChain scale(int scale) {
        this.result = result.setScale(scale);
        return this;
    }

    /**
     * 精度 保留小数模式
     */
    public BigDecimalChain scale(int scale, RoundingMode roundingMode) {
        this.result = result.setScale(scale, roundingMode);
        return this;
    }

    /** 获取最终结果 */
    public BigDecimal get() {
        return result;
    }

    /** 判断是否数字 */
    private static void isNumber(String v) {
            if(!NumberUtil.isNumber(v)) {
            throw new NumberFormatException("非数字入参，请输入有效的数字");
        }
    }

}
